本篇是實作常用的 AWS Route53 服務之 Terraform 模組,並且會使用到 YAML 資料結構來定義模組的內容,完整的專案程式碼分享在我的 Github 上。
my_dns
的放置位置 modules/my_dns
:├── configs
│ ├── cloudfront
│ │ └── distributions.yaml
│ ├── cloudwatch
│ │ └── loggroups.yaml
│ ├── dynamodb
│ │ └── configurations.yaml
│ ├── ecr
│ │ ├── lifecycle_policy.json
│ │ ├── permission_policy.json
│ │ └── repos.yaml
│ ├── iam
│ │ ├── assume_role_policies
│ │ │ ├── eks-cluster.json
│ │ │ ├── eks-fargate-pod-execution-role.json
│ │ │ └── eks-node-group.json
│ │ ├── iam.yaml
│ │ ├── role_policies
│ │ │ └── eks-cluster-cloudwatch-metrics.json
│ │ └── user_policies
│ │ └── admin_access.json
│ ├── kinesis
│ │ └── streams.yaml
│ ├── kms
│ │ ├── keys.yaml
│ │ └── policies
│ │ └── my-key-policy.json
│ ├── r53
│ │ └── records.yaml
│ ├── s3
│ │ ├── policies
│ │ │ └── my-bucket.json
│ │ └── s3.yaml
│ ├── subnet
│ │ └── my-subnets.yaml
│ └── vpc
│ └── my-vpcs.yaml
├── example.tfvars
├── locals.tf
├── main.tf
├── modules
│ ├── my_aws_load_balancer_controller
│ ├── my_cloudfront
│ ├── my_cloudwatch
│ ├── my_dns
│ │ ├── main.tf
│ │ ├── provider.tf
│ │ └── variables.tf
│ ├── my_dns
│ ├── my_dynamodb
│ ├── my_ecr
│ ├── my_eips
│ ├── my_eks
│ ├── my_eventbridge
│ ├── my_iam
│ ├── my_igw
│ ├── my_instances
│ ├── my_karpenter
│ ├── my_kinesis_stream
│ ├── my_kms
│ ├── my_msk
│ ├── my_nacls
│ ├── my_route_tables
│ ├── my_s3
│ ├── my_subnets
│ └── my_vpc
├── my-ingress-controller-values.yaml
├── my-ingress-node-red.yaml
├── packer
│ └── apache-cassandra
└── variables.tf
./configs/r53/records.yaml
內容來定義 AWS Route53 需要用建立的資源:alias:
- alias_target:
dns_name: "<ALIAS_DNS_NAME>"
evaluate_target_health: <true or false>
hosted_zone_id: Z31USIVHYNEOWT
name: "<ALIAS_DNS_NAME>"
type: <"A" or "CNAME">
simple:
- name: "<SIMPLE_NAME>"
records:
- <RECORD>
ttl: <TTL>
type: <"A" or "CNAME">
tags: []
vpcs:
- vpc_id: vpc-0ee88268758ca392c
vpc_region: ap-northeast-1
zone_id: Z04227961BT9BSTA95P7
my_dns
模組:./modules/my_dns/provider.tf
:provider "aws" {
region = var.aws_region
profile = var.aws_profile
}
./modules/my_dns/variables.tf
:variable "aws_region" {
description = "AWS region"
default = "ap-northeast-1"
}
variable "aws_profile" {
description = "AWS profile"
default = ""
}
variable "project_name" {
type = string
description = "Project name"
default = ""
}
variable "department_name" {
type = string
description = "Department name"
default = "SRE"
}
variable "domain_name" {
type = string
description = "The domain name of records"
}
variable "record_path" {
type = string
description = "The path of records"
}
./modules/my_dns/main.tf
:resource "aws_route53_zone" "r53zone" {
name = var.domain_name
dynamic "vpc" {
for_each = local.vpcs
content {
vpc_id = vpc.value["vpc_id"]
vpc_region = vpc.value["vpc_region"]
}
}
tags = { for tag in local.tags : tag.key => tag.value }
}
locals {
record_simple = yamldecode(file("${var.record_path}"))["simple"]
record_alias = yamldecode(file("${var.record_path}"))["alias"]
vpcs = yamldecode(file("${var.record_path}"))["vpcs"]
tags = yamldecode(file("${var.record_path}"))["tags"]
}
resource "aws_route53_record" "simples" {
for_each = { for r in local.record_simple : r.name => r }
zone_id = aws_route53_zone.r53zone.id
name = each.value.name
type = each.value.type
ttl = each.value.ttl
records = each.value.records
}
resource "aws_route53_record" "aliases" {
for_each = { for r in local.record_alias : r.name => r }
zone_id = aws_route53_zone.r53zone.id
name = each.value.name
type = each.value.type
alias {
name = each.value.alias_target.dns_name
zone_id = each.value.alias_target.hosted_zone_id
evaluate_target_health = each.value.alias_target.evaluate_target_health
}
}
example.tfvars
:aws_region="ap-northeast-1"
aws_profile="<YOUR_PROFILE>"
project_name="example"
department_name="SRE"
cassandra_root_password="<CASSANDRA_ROOT_PASSWORD>"
main.tf
:terraform {
required_providers {
aws = {
version = "5.15.0"
}
}
backend "s3" {
bucket = "<YOUR_S3_BUCKET_NAME>"
dynamodb_table = "<YOUR_DYNAMODB_TABLE_NAME>"
key = "terraform.tfstate"
region = "ap-northeast-1"
shared_credentials_file = "~/.aws/config"
profile = "<YOUR_PROFILE>"
}
}
其他模組省略...
# route53
module "dns_nxdnet" {
aws_region = var.aws_region
aws_profile = var.aws_profile
record_path = "./configs/r53/records.yaml"
domain_name = "domain.my"
source = "./modules/my_dns"
}
domain.my
來測試一下模組:alias: []
simple: []
tags: []
vpcs:
- vpc_id: vpc-049f62a6dc464cb1c
vpc_region: ap-northeast-1
terraform init && terraform plan --out .plan -var-file=example.tfvars
來確認一下結果:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create
Terraform will perform the following actions:
# module.route53.aws_route53_zone.r53zone will be created
+ resource "aws_route53_zone" "r53zone" {
+ arn = (known after apply)
+ comment = "Managed by Terraform"
+ force_destroy = false
+ id = (known after apply)
+ name = "domain.my"
+ name_servers = (known after apply)
+ primary_name_server = (known after apply)
+ tags_all = (known after apply)
+ zone_id = (known after apply)
+ vpc {
+ vpc_id = "vpc-049f62a6dc464cb1c"
+ vpc_region = "ap-northeast-1"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
──────────────────────────────────────────────────────────────────────────
Saved the plan to: .plan
To perform exactly these actions, run the following command to apply:
terraform apply ".plan"
Releasing state lock. This may take a few moments...
terraform apply ".plan"
來跑執行計畫建立 AWS Route53 Zone 來確認一下結果:module.route53.aws_route53_zone.r53zone: Creating...
module.route53.aws_route53_zone.r53zone: Still creating... [10s elapsed]
module.route53.aws_route53_zone.r53zone: Still creating... [20s elapsed]
module.route53.aws_route53_zone.r53zone: Still creating... [30s elapsed]
module.route53.aws_route53_zone.r53zone: Still creating... [40s elapsed]
module.route53.aws_route53_zone.r53zone: Still creating... [50s elapsed]
module.route53.aws_route53_zone.r53zone: Creation complete after 54s [id=Z0762953IV1MDMFQZDFM]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
terraform state show 'module.route53.aws_route53_zone.r53zone'
來確認一下建立完成的 AWS Route53 Zone ID:# module.route53.aws_route53_zone.r53zone:
resource "aws_route53_zone" "r53zone" {
arn = "arn:aws:route53:::hostedzone/Z0762953IV1MDMFQZDFM"
comment = "Managed by Terraform"
force_destroy = false
id = "Z0762953IV1MDMFQZDFM"
name = "domain.my"
name_servers = [
"ns-0.awsdns-00.com.",
"ns-1024.awsdns-00.org.",
"ns-1536.awsdns-00.co.uk.",
"ns-512.awsdns-00.net.",
]
primary_name_server = "ns-0.awsdns-00.com."
tags_all = {}
zone_id = "Z0762953IV1MDMFQZDFM"
vpc {
vpc_id = "vpc-049f62a6dc464cb1c"
vpc_region = "ap-northeast-1"
}
}
./configs/r53/records.yaml
:alias:
- alias_target:
dns_name: k8s-nginxing-mynginxi-420ab563fa-0e4d90abe2740adb.elb.ap-northeast-1.amazonaws.com.
evaluate_target_health: false
hosted_zone_id: Z31USIVHYNEOWT
name: alias-test
type: CNAME
simple:
- name: simple-test
records:
- 10.4.3.2
ttl: 300
type: A
tags: []
vpcs:
- vpc_id: vpc-049f62a6dc464cb1c
vpc_region: ap-northeast-1
zone_id: Z04227961BT9BSTA95P7
terraform plan --out .plan -var-file=example.tfvars
來確認一下結果:module.route53.aws_route53_zone.r53zone: Refreshing state... [id=Z0762953IV1MDMFQZDFM]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
+ create
Terraform will perform the following actions:
# module.route53.aws_route53_record.aliases["alias-test"] will be created
+ resource "aws_route53_record" "aliases" {
+ allow_overwrite = (known after apply)
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "alias-test"
+ type = "CNAME"
+ zone_id = "Z0762953IV1MDMFQZDFM"
+ alias {
+ evaluate_target_health = false
+ name = "k8s-nginxing-mynginxi-420ab563fa-0e4d90abe2740adb.elb.ap-northeast-1.amazonaws.com"
+ zone_id = "Z31USIVHYNEOWT"
}
}
# module.route53.aws_route53_record.simples["simple-test"] will be created
+ resource "aws_route53_record" "simples" {
+ allow_overwrite = (known after apply)
+ fqdn = (known after apply)
+ id = (known after apply)
+ name = "simple-test"
+ records = [
+ "10.4.3.2",
]
+ ttl = 300
+ type = "A"
+ zone_id = "Z0762953IV1MDMFQZDFM"
}
Plan: 2 to add, 0 to change, 0 to destroy.
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Saved the plan to: .plan
To perform exactly these actions, run the following command to apply:
terraform apply ".plan"
Releasing state lock. This may take a few moments...
下一篇文章將會介紹有哪些 Pre-commit 工具可以來檢查與管理 Terrform 專案。